package com.chen.tliaswebtest.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author chen
 * @version 1.0
 * @create_date 2025/7/26
 * AOP 切面类,练习用的
 */
@Slf4j
@Aspect
@Component
public class TliasAspect {

    //切入点方法execution（公共的切入点表达式），简化切入点表达式，实现复用
    //@Pointcut("execution(* com.chen.tliaswebtest.controller.*.*(..))")
    @Pointcut("")
    private void pt() {
    }

    // 切入点方法基于注解的方式，比较灵活
    @Pointcut("")
    private void at() {
    }

    // 拦截所有 com.chen.tliaswebtest.controller 包下的所有方法
    // 计算方法执行时长
    // 环绕通知
    @Around("at()")
    public Object recordTime(ProceedingJoinPoint point) throws Throwable {// 在这里抛出异常给全局异常处理就可以
        log.info("@Around开始执行方法: {}", point.getSignature().getName());
        long start = System.currentTimeMillis();
        Object result = point.proceed();
        long end = System.currentTimeMillis();
        log.info("@Around方法执行完毕: {}, 耗时: {}ms", point.getSignature().getName(), end - start);
        return result;
    }


    // 前置通知
    @Before("pt()")
    public void before(JoinPoint joinPoint) {
        log.info("@Before方法开始执行: {}", joinPoint.getSignature());
        log.info("参数: {}", joinPoint.getArgs());
        log.info("目标对象: {}", joinPoint.getTarget());
    }

    // 后置通知
    @After("pt()")
    public void after(JoinPoint joinPoint) {
        log.info("@After方法结束执行: {}", joinPoint.getSignature());
    }

    // 返回后通知
    @AfterReturning(value = "pt()", returning = "result")
    public Object afterReturning(JoinPoint joinPoint, Object result) {
        log.info("@AfterReturning方法结束执行: {}, 返回值: {}", joinPoint.getSignature(), result);
        return result;
    }

    // 异常后通知
    @AfterThrowing(value = "pt()", throwing = "e")
    public Exception afterThrowing(JoinPoint joinPoint, Exception e) {
        log.info("@AfterThrowing方法结束执行: {}, 异常: {}", joinPoint.getSignature(), e.getMessage());
        return e;
    }
}
